package org.acghub.mtdb.common;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @author zhouhe
 */
public interface Compilable {
    boolean isResolved();

    void setResolved(boolean resolved);

    Set<? extends Compilable> getChildren();

    boolean resolve();

    default void compile0(Set<Compilable> unresolved) {
        for (int target = 0; target != getChildren().size(); ) {
            target = getChildren().size();
            for (Compilable child : new ArrayList<>(getChildren())) {
                child.compile0(unresolved);
            }
        }
        if (!this.isResolved()) {
            if (this.resolve()) {
                this.setResolved(true);
            } else {
                unresolved.add(this);
            }
        }
    }

    default Set<Compilable> compile() {
        Set<Compilable> unresolved = new LinkedHashSet<>();
        // 首次编译
        this.compile0(unresolved);
        // 后续继续编译, 要么编译通过, 要么有循环依赖
        for (int target = 0; target != unresolved.size(); ) {
            target = unresolved.size();
            List<Compilable> compiles = new ArrayList<>(unresolved);
            unresolved = new LinkedHashSet<>();
            for (Compilable compile : compiles) {
                compile.compile0(unresolved);
            }
        }
        return unresolved;
    }
}
